#include<iostream>
#include<memory>
struct Date
{
public:
    Date(int year = 1, int month = 2, int day = 3)
        :_year(year), _month(month), _day(day)
    {
        std::cout << _year << ":" << _month << ":" << _day << std::endl;
    }
    ~Date()
    {
        std::cout << "~Date()" << std::endl;
    }
    int _year;
    int _month;
    int _day;
};
int main()
{
    //auto_ptr(不推荐,有指针悬空问题,此用法高版本的编译器已经被移出)
    std::auto_ptr<Date> ap1(new Date(5, 6, 7));//会被置空
    std::auto_ptr<Date> ap2(ap1);//会拿到原ap1的资源
    //std::cout << ap1 << std::endl;


    //unique_ptr(又叫唯一指针,不需要拷贝的场景建议使用,不支持拷贝构造和拷贝赋值)使用move对象也会造成指针悬空
    std::unique_ptr<Date> up1(new Date(5, 6, 7));
    //std::unique_ptr<Date> up2(up1);//报错因为拷贝构造和拷贝赋值已经被删除
    std::unique_ptr<Date> up2(std::move(up1));//指针悬空
    //std::cout << up2 << std::endl;//只能指针本身就可以打印,结果是管理资源的地址


    //shared_ptr(又叫共享指针,支持拷贝构造,也支持移动构造,底层采用引用计数的方式进行实现)

    std::shared_ptr<Date> sp1(new Date);
    std::shared_ptr<Date> sp2(sp1);
    std::shared_ptr<Date> sp3(sp2);
    //使用use_count函数可以查看管理资源的对象的个数
    std::cout << sp1.use_count() << std::endl;
    std::cout << sp2.use_count() << std::endl;
    std::cout << sp3.use_count() << std::endl;
    //也可以使用－>去访问资源
    std::cout << sp2->_year << " " << sp2->_month << " " << sp2->_day << std::endl;
    std::cout << sp3->_year << " " << sp3->_month << " " << sp3->_day << std::endl;
    sp1->_year++;
    std::cout << sp2->_year << " " << sp2->_month << " " << sp2->_day << std::endl;
    std::cout << sp3->_year << " " << sp3->_month << " " << sp3->_day << std::endl;

    std::shared_ptr<Date> sp4(std::move(sp3));//会有悬空问题
    std::cout << sp4 << std::endl;
    //只能指针应该谨慎使用移动
    //只有shared_ptr可以直接打印智能指针本身(不同版本实现方式不同,有的支持有的不支持)
    //打印管理对象的地址我可以使用get函数来获得管理对象的地址
    std::cout << sp4.get() << std::endl;
    std::cout << up2.get() << std::endl;
    std::cout << ap2.get() << std::endl;
    return 0;
}
